/*
   Copyright (c) 2005 Lucas Mello Schnorr <schnorr@gmail.com>
   
   This file is part of DIMVisual.
   
   DIMVisual is free software; you can redistribute it and/or modify it under
   the terms of the GNU Lesser General Public License as published by the
   Free Software Foundation; either version 2 of the License, or (at your
   option) any later version.
   
   DIMVisual is distributed in the hope that it will be useful, but WITHOUT ANY
   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
   for more details.
   
   You should have received a copy of the GNU Lesser General Public License
   along with DIMVisual; if not, write to the Free Software Foundation, Inc.,
   59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
#include "MPIRASTROConverter.h"
#include "OneToOne.h"

static OneToOne *sendrecv;
static NSMutableDictionary *async;

@implementation MPIRASTROConverter (SendRecv)
- (id) convertEventSendRecv: (MPIRASTROEvent *) event 
{
	NSMutableArray *ret = [[NSMutableArray alloc] init];
	NSString *container = [provider identifierForEntity: 
		[NSArray arrayWithObjects: @"Machine", @"Thread", nil]
				ids:
		[NSArray arrayWithObjects:[event machine],[event thread],nil]];

	if (async == nil){
		async = [[NSMutableDictionary alloc] init];
	}
	if (sendrecv == nil){
		sendrecv = [[OneToOne alloc] init];
	}
	if (container == nil){
		[ret release];
		return nil;
	}
	
	int etype = atoi ([[event type] cString]);

	/* MPI_SEND_IN */
        if (etype == MPI_SEND_IN){
		NSString *count = [event int32AtIndex: 0];
		NSString *receiver = [event int32AtIndex: 1];
		NSString *tag = [event int32AtIndex: 2];
		NSString *sender = [event node];
		
		[ret addObjectsFromArray: 
			[sendrecv containerSend: container
			andSenderNode: sender
			andReceiverNode: receiver
			andTime: [event time]
			andOperation: @"send-recv"
			andProvider: provider]];

		PajeSetState *set;
		set = [self addPajeSetState: @"MPI_SEND"
					time: [event time]
					container: container];
		[set retain];
		[set addFieldNamed: @"TAG" withType: @"string"];
		[set addFieldNamed: @"COUNT" withType: @"string"];
		[set setValue: tag forFieldNamed: @"TAG"];
		[set setValue: count forFieldNamed: @"COUNT"];
		[ret addObject: set];
		[set release];
	
	/* MPI_ISEND_IN */
	}else if (etype == MPI_ISEND_IN){
		NSString *count = [event int32AtIndex: 0];
		NSString *tag = [event int32AtIndex: 1];
		NSString *receiver = [event int32AtIndex: 2];
		NSString *sender = [event node];
		
		[ret addObjectsFromArray: 
			[sendrecv containerSend: container
			andSenderNode: sender
			andReceiverNode: receiver
			andTime: [event time]
			andOperation: @"send-recv"
			andProvider: provider]];

		PajeSetState *set;
		set = [self addPajeSetState: @"MPI_ISEND"
					time: [event time]
					container: container];
		[set retain];
		[set addFieldNamed: @"TAG" withType: @"string"];
		[set addFieldNamed: @"COUNT" withType: @"string"];
		[set setValue: tag forFieldNamed: @"TAG"];
		[set setValue: count forFieldNamed: @"COUNT"];
		[ret addObject: set];
		[set release];

	/* MPI_RECV_IN */
        }else if (etype == MPI_RECV_IN){
		NSString *count = [event int32AtIndex: 0];
		NSString *tag = [event int32AtIndex: 1];

		PajeSetState *set;
		set = [self addPajeSetState: @"MPI_RECV"
					time: [event time]
					container: container];
		[set retain];
		[set addFieldNamed: @"TAG" withType: @"string"];
		[set addFieldNamed: @"COUNT" withType: @"string"];
		[set setValue: tag forFieldNamed: @"TAG"];
		[set setValue: count forFieldNamed: @"COUNT"];
		[ret addObject: set];
		[set release];
	
	/* MPI_IRECV_IN */
	}else if (etype == MPI_IRECV_IN){
		NSString *count = [event int32AtIndex: 0];
		NSString *tag = [event int32AtIndex: 1];
//		NSString *sender = [event int32AtIndex: 2];
	
		/*
		[async setObject: sender forKey: container];
		*/

		PajeSetState *set;
		set = [self addPajeSetState: @"MPI_IRECV"
					time: [event time]
					container: container];
		[set retain];
		[set addFieldNamed: @"TAG" withType: @"string"];
		[set addFieldNamed: @"COUNT" withType: @"string"];
		[set setValue: tag forFieldNamed: @"TAG"];
		[set setValue: count forFieldNamed: @"COUNT"];
		[ret addObject: set];
		[set release];

	
	/* MPI_WAIT_IN */
	}else if (etype == MPI_WAIT_IN){
		[ret addObject: [self addPajeSetState: @"MPI_WAIT" time: [event time] container: container]];
	
	/* MPI_IRECV_OUT */
	}else if (etype == MPI_IRECV_OUT){
		[ret addObject: [self addPajeSetState: @"running" time: [event time] container: container]];

	/* MPI_WAIT_OUT */
	}else if (etype == MPI_WAIT_OUT){
		/*
		NSString *sender = [async objectForKey: container];
		if (sender != nil){
			[ret addObjectsFromArray:
				[sendrecv containerReceive: container
					andReceiverNode: [event node]
					andSenderNode: sender
					andTime: [event time]
					andOperation: @"send-recv"
					andProvider: provider]];
			[async removeObjectForKey: container];
		}else{
			NSLog (@"Sender is nil");
		}	
		*/
		[ret addObject: [self addPajeSetState: @"running" time: [event time] container: container]];
	/* MPI_SEND_OUT */
	}else if (etype == MPI_SEND_OUT){
		[ret addObject: [self addPajeSetState: @"running" time: [event time] container: container]];

	/* MPI_RECV_OUT */
	}else if (etype == MPI_RECV_OUT){
		NSString *sender = [event int32AtIndex: 0];
		NSString *receiver = [event node];
		
		NSMutableArray *x = 
			[sendrecv containerReceive: container
				andReceiverNode: receiver
				andSenderNode: sender
				andTime: [event time]
				andOperation: @"send-recv"
				andProvider: provider];
		[ret addObjectsFromArray: x];
		[ret addObject: [self addPajeSetState: @"running" time: [event time] container: container]];

		/* not instrumented below 
	}else if (etype == MPI_BSEND_IN){
		[ret addObject: [self addPajeSetState: @"MPI_BSEND" time: [event time] container: container]];
      }else if (etype == MPI_BSEND_INIT_IN){
		[ret addObject: [self addPajeSetState: @"MPI_BSEND_INIT" time: [event time] container: container]];
      }else if (etype == MPI_RECV_INIT_IN){
		[ret addObject: [self addPajeSetState: @"MPI_RECV_INIT" time: [event time] container: container]];
      }else if (etype == MPI_SSEND_IN){
		[ret addObject: [self addPajeSetState: @"MPI_SSEND" time: [event time] container: container]];
      }else if (etype == MPI_SEND_INIT_IN){
		[ret addObject: [self addPajeSetState: @"MPI_SEND_INIT" time: [event time] container: container]];
      }else if (etype == MPI_IBSEND_IN){
		[ret addObject: [self addPajeSetState: @"MPI_IBSEND" time: [event time] container: container]];
      }else if (etype == MPI_IPROBE_IN){
		[ret addObject: [self addPajeSetState: @"MPI_IPROBE" time: [event time] container: container]];
      }else if (etype == MPI_IRSEND_IN){
		[ret addObject: [self addPajeSetState: @"MPI_IRSEND" time: [event time] container: container]];
      }else if (etype == MPI_ISSEND_IN){
		[ret addObject: [self addPajeSetState: @"MPI_ISSEND" time: [event time] container: container]];
      }else if (etype == MPI_PROBE_IN){
		[ret addObject: [self addPajeSetState: @"MPI_PROBE" time: [event time] container: container]];
      }else if (etype == MPI_RSEND_IN){
		[ret addObject: [self addPajeSetState: @"MPI_RSEND" time: [event time] container: container]];
      }else if (etype == MPI_RSEND_INIT_IN){
		[ret addObject: [self addPajeSetState: @"MPI_RSEND_INIT" time: [event time] container: container]];
      }else if (etype == MPI_SENDRECV_IN){
		[ret addObject: [self addPajeSetState: @"MPI_SENDRECV" time: [event time] container: container]];
      }else if (etype == MPI_SENDRECV_REPLACE_IN){
		[ret addObject: [self addPajeSetState: @"MPI_SENDRECV_REPLACE" time: [event time] container: container]];
      }else if (etype == MPI_SSEND_INIT_IN){
		[ret addObject: [self addPajeSetState: @"MPI_SSEND_INIT" time: [event time] container: container]];
      }else if (etype == MPI_WAITALL_IN){
		[ret addObject: [self addPajeSetState: @"MPI_WAITALL" time: [event time] container: container]];
      }else if (etype == MPI_WAITANY_IN){
		[ret addObject: [self addPajeSetState: @"MPI_WAITANY" time: [event time] container: container]];
      }else if (etype == MPI_WAITSOME_IN){
		[ret addObject: [self addPajeSetState: @"MPI_WAITSOME" time: [event time] container: container]];
      }else if (etype == MPI_ISEND_OUT
			|| etype == MPI_IRSEND_OUT
			|| etype == MPI_BSEND_OUT
			|| etype == MPI_BSEND_INIT_OUT
			|| etype == MPI_RECV_INIT_OUT
			|| etype == MPI_SEND_INIT_OUT
			|| etype == MPI_IBSEND_OUT
			|| etype == MPI_ISSEND_OUT
			|| etype == MPI_RSEND_OUT
			|| etype == MPI_RSEND_INIT_OUT
			|| etype == MPI_SENDRECV_OUT
			|| etype == MPI_SENDRECV_REPLACE_OUT
			|| etype == MPI_SSEND_OUT
			|| etype == MPI_SSEND_INIT_OUT
			|| etype == MPI_WAITALL_OUT
			|| etype == MPI_WAITANY_OUT
			|| etype == MPI_WAITSOME_OUT){
		[ret addObject: [self addPajeSetState: @"running" time: [event time] container: container]];
*/
	}
	[ret autorelease];
	return ret;
}
@end

